/*
 * Copyright 2010 WANdisco, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */
#include <string.h>
#include "jniutil.h"

jstring
make_jstring(JNIEnv *env, const char *c) {
  return c != NULL ? (*env)->NewStringUTF(env, c): NULL;
}

jstring
make_jstring2(JNIEnv *env, const svn_string_t *s) {
  return s != NULL ? (*env)->NewStringUTF(env, s->data): NULL;
}

jbyteArray
make_jbyteArray(JNIEnv *env, const svn_string_t *s) {
  jbyteArray ret = NULL;
  if (s != NULL) {
    printf("make_jbyteArray(len=%"APR_SIZE_T_FMT")\n", s->len);
    ret = (*env)->NewByteArray(env, s->len);
    if (ret != NULL) {
      (*env)->SetByteArrayRegion(env, ret, 0, s->len, (jbyte*)(s->data));
    }
  }
  return ret;
}

char *
make_cstring(JNIEnv *env, jstring jstr, apr_pool_t *pool) {
  char *ret = NULL;
  if (jstr != NULL) {
    const char *tmp;
    jsize jlen = (*env)->GetStringLength(env, jstr);
    ret = apr_pcalloc(pool, jlen + 1);
    tmp = (*env)->GetStringUTFChars(env, jstr, NULL);
    strncpy(ret, tmp, jlen);
    ret[jlen] = 0;
    (*env)->ReleaseStringUTFChars(env, jstr, tmp);
  }
  
  return ret;
}

svn_string_t *
make_cstring2(JNIEnv *env, jstring jstr, apr_pool_t *pool) {
  const char *str;
  svn_string_t* ret = NULL;

  str = make_cstring(env, jstr, pool);
  if (str) {
    ret = svn_string_create(str, pool);
  }
  return ret;
}

void
throw_exception(JNIEnv *env, const char *cname, const char *msg) {
  jclass clazz = (*env)->FindClass(env, cname);
  if (clazz) {
    (*env)->ThrowNew(env, clazz, msg);
  }
}

jstring
assemble_error_message(JNIEnv *env, svn_error_t *err, apr_pool_t *pool){
  char buf[1024];
  if (err->apr_err > APR_OS_START_USEERR
      && err->apr_err <= APR_OS_START_CANONERR) {
    svn_strerror(err->apr_err, buf, sizeof(buf));
  } else {
    apr_strerror(err->apr_err, buf, sizeof(buf));
  }
  return make_jstring(env, buf);
}

void
throw_svn_exception(JNIEnv *env, svn_error_t *err, svn_boolean_t clear_existing) {
  if (err->apr_err != SVN_NO_ERROR && err->apr_err < SVNJ_ERROR_START) {
    char errbuf[512];
    const char *cname;
    if ((*env)->ExceptionCheck(env)) {
      if (clear_existing) {
        (*env)->ExceptionClear(env);
      } else {
        /* Must clear existing SVN exception in all cases */
        svn_error_clear(err);
        return; /* keep existing exception */
      }
    }
    /* FIXME: this doesn't seem to really propagate custom
     * error messages correctly.  Seems to be problem in
     * guts of svn.
     */
    /*
      FIXME: introduce SVNJException, with a member for
      the svn_error_t's code (type apr_status_t)
     */
    
    /*svn_err_best_message(svn_error_root_cause(err), errbuf, sizeof(errbuf));*/
    svn_strerror(err->apr_err, errbuf, sizeof(errbuf));
    if (strlen(errbuf) <= 1) {
      sprintf(errbuf, "apr/svn error %d\n", err->apr_err);
    }
    switch (err->apr_err) {
    case SVN_ERR_FS_NOT_FOUND:
      cname = "java/io/FileNotFoundException"; break;
    default:
      cname = "java/lang/RuntimeException"; break;
    }
    /*printf("[jniutil.c] svn error %d\n", err->apr_err);
    fprintf(stderr, "[jniutil] raising exception with errmsg '%s' len=%d '%s'\n",
      errbuf, strlen(errbuf), err->message);*/
    /* Must clear existing SVN exception in all cases */
    svn_error_clear(err);
    throw_exception(env, cname, errbuf);
  }
}

/** FIXME: make sure that when this is called, that
 * a matching svn_error_clear() is called at some point...
 */
svn_error_t *
exception_to_svn_err(JNIEnv *env) {
  if ((*env)->ExceptionCheck(env)) {
    return svn_error_create(SVNJ_ERROR_START, NULL,
                            "SVNJ exception occurred in java");
  }
  return SVN_NO_ERROR;
}

/* don't think i need this
jstring
assemble_error_message(JNIEnv *env, svn_error_t *err, apr_pool_t *pool) {
  
}
*/
